package org.iabako.server.controller.timer.business;

import org.apache.log4j.Logger;
import org.iabako.server.dao.business.InstallmentDAO;
import org.iabako.server.dao.business.PaymentRequestDAO;
import org.iabako.server.dao.user.EnterpriseDAO;
import org.iabako.server.mail.IabakoMailHelper;
import org.iabako.server.mail.IabakoMailSender;
import org.iabako.server.tools.BundleMessages;
import org.iabako.server.tools.ServerTools;
import org.iabako.shared.entity.business.Installment;
import org.iabako.shared.entity.business.PaymentRequestConfig;
import org.iabako.shared.entity.user.Enterprise;
import org.iabako.shared.iservice.business.ClientConversationService;
import org.iabako.shared.tools.GenericTools;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.MailException;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * Created by jose on 30/01/15.
 */

@Controller
public class SendPaymentRequestControllerTimer {

    static Logger log = Logger.getLogger(CreatePastInstallmentsControllerTimer.class.getName());

    @Autowired
    private InstallmentDAO installmentDAO;
    @Autowired
    private EnterpriseDAO enterpriseDAO;
    @Autowired
    private PaymentRequestDAO paymentRequestDAO;
    @Autowired
    IabakoMailSender iabakoMailSender;
    @Autowired
    ClientConversationService clientConversationService;
    @Autowired
    BundleMessages messages;

    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    // every day at 01:00 AM
    @Scheduled(cron = "0 0 1 * * ?")
    //@Scheduled(initialDelay = 10000, fixedRate = 60000)
    public void action() throws Exception {
        log.info("Executing SendPaymentRequestControllerTimer...");

        List<Enterprise> enterprises = enterpriseDAO.getActiveEnterprises();
        List<PaymentRequestConfig> paymentRequestsBeforeList = paymentRequestDAO.getActivePaymentRequestList(enterprises);
        log.info("Number of active PaymentRequestConf : " + paymentRequestsBeforeList.size());

        ServerTools serverTools = new ServerTools();
        Date today = serverTools.resetTime(new Date());

        int consecutiveMailException = 0;

        for (PaymentRequestConfig payReqConf : paymentRequestsBeforeList) {

            List<Installment> installmentList = new ArrayList<Installment>();

            //join Client is mandatory (we do this to send an email to clients)
            installmentList.addAll(installmentDAO.getInstallmentsForRequestBetween(payReqConf, true));
            installmentList.addAll(installmentDAO.getInstallmentsForRequestBetween(payReqConf, false));

            boolean beforePaymentEmail = false;

            log.info("Number of PaymentRequestEmail to send : " + installmentList.size());

            for (Installment installment : installmentList) {

                if (installment.getDate().compareTo(today) >= 0 && payReqConf.getDaysBeforePayment() >= 0) {
                    beforePaymentEmail = true;
                }

                Enterprise enterprise = payReqConf.getEnterprise();

                String[] productServiceList = installment.getSale().getProductsServicesAsString().split("\n");
                String productServiceString = "";

                for (String productService : productServiceList) {
                    productService = productService.substring(0, productService.lastIndexOf("("));
                    productServiceString += "- " + productService + "\n";
                }

                String subjectKey = "payment_request_mail_subject_value";

                String bodyKey = beforePaymentEmail ?
                        "payment_request_mail_before_default_body" : "payment_request_mail_after_default_body";

                String subject = messages.getLabel(enterprise.getLanguage(), subjectKey, GenericTools.formatDate(installment.getDate()));

                String body = messages.getLabel(enterprise.getLanguage(), bodyKey,
                        installment.getSale().getClient().getName(),
                        GenericTools.formatDate(new Date()),
                        ServerTools.formatAmount(enterprise.getLanguage(), installment.getAmount()) + "",
                        productServiceString);

                body = addCustomBodyAndFooter(payReqConf, beforePaymentEmail, body, enterprise);

                body = body.replace("</span>", "").replace("<span>", "").replace("<br/>", "\n");

                IabakoMailHelper iabakoMailHelper = new IabakoMailHelper(null,
                        payReqConf.getEnterprise().getName(),
                        installment.getSale().getClient().getEmail(),
                        subject, body);

                iabakoMailHelper.setNoReplyEmail(true);
                iabakoMailHelper.setEnterprise(enterprise);
                iabakoMailHelper.setDisableIabakoLogo(true);
                iabakoMailHelper.setAddEnterpriseLogo(true);
                iabakoMailHelper.setDisableDefaultFooter(true);
                iabakoMailHelper.setEnablePoweredByFooter(true);

                try {
                    sentMail(installment.getSale().getClient().getId(), installment, iabakoMailHelper, beforePaymentEmail);
                    consecutiveMailException = 0;

                } catch (MailException e) {
                    log.error(e.getMessage(), e);
                    consecutiveMailException++;
                    if (consecutiveMailException > 10) {
                        log.error("SendPaymentRequestControllerTimer stopped because 10 consecutive MailException");
                        return;
                    }
                }
            }
        }
        log.info("SendPaymentRequestControllerTimer ends successfully");
    }

    private String addCustomBodyAndFooter(PaymentRequestConfig payReqConf, boolean beforePaymentEmail, String body, Enterprise enterprise) {
        if (beforePaymentEmail) {
            if (payReqConf.getEmailBeforePaymentBody() != null) {
                body += "\n" + payReqConf.getEmailBeforePaymentBody();
            }
            if (payReqConf.getEmailBeforePaymentFooter() != null) {
                body += "\n\n" + payReqConf.getEmailBeforePaymentFooter();
            } else {
                body += "\n\n" + messages.getLabel(enterprise.getLanguage(), "payment_request_mail_footer", enterprise.getName());
            }
        } else {
            if (payReqConf.getEmailAfterPaymentBody() != null) {
                body += "\n" + payReqConf.getEmailAfterPaymentBody();
            }
            if (payReqConf.getEmailAfterPaymentFooter() != null) {
                body += "\n\n" + payReqConf.getEmailAfterPaymentFooter();
            } else {
                body += "\n\n" + messages.getLabel(enterprise.getLanguage(), "payment_request_mail_footer", enterprise.getName());
            }
        }
        return body;
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    private void sentMail(Long idClient, Installment installment, IabakoMailHelper iabakoMailHelper, boolean beforePaymentMail) throws MailException {
        boolean sent = iabakoMailSender.sendMail(iabakoMailHelper);
        if (sent) {
            installmentDAO.setRequestPaymentSent(installment, beforePaymentMail);
            clientConversationService.addConversationFromEmail(idClient, iabakoMailHelper.getTo().get(0), iabakoMailHelper);
        }
    }
}
